/**
 * Copyright 2019 吉鼎科技.

 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.easyplatform.services.job;

import cn.easyplatform.EasyPlatformWithLabelKeyException;
import cn.easyplatform.ScriptEvalException;
import cn.easyplatform.cfg.EngineConfiguration;
import cn.easyplatform.contexts.Contexts;
import cn.easyplatform.contexts.EngineContext;
import cn.easyplatform.contexts.RecordContext;
import cn.easyplatform.dao.BizDao;
import cn.easyplatform.dos.EnvDo;
import cn.easyplatform.dos.FieldDo;
import cn.easyplatform.dos.Record;
import cn.easyplatform.dos.UserDo;
import cn.easyplatform.entities.beans.LogicBean;
import cn.easyplatform.i18n.I18N;
import cn.easyplatform.interceptor.CommandContext;
import cn.easyplatform.services.IProjectService;
import cn.easyplatform.spi.engine.EngineFactory;
import cn.easyplatform.type.DeviceType;
import cn.easyplatform.type.FieldType;
import cn.easyplatform.type.UserType;
import cn.easyplatform.util.RuntimeUtils;
import com.alibaba.fastjson.JSON;
import org.apache.shiro.SecurityUtils;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author <a href="mailto:davidchen@epclouds.com">littleDog</a> <br/>
 * @since 2.0.0 <br/>
 */
public class DynamicJobWorker implements Job {

    private static final Logger log = LoggerFactory.getLogger(DynamicJobWorker.class);

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        EngineContext ec = (EngineContext) EngineFactory.me();
        EngineConfiguration engineConfiguration = ec.getEngineConfiguration();
        long id = Long.parseLong(context.getJobDetail().getKey().getName());
        String pid = (String) context.getTrigger().getJobDataMap().get("pid");
        IProjectService ps = (IProjectService) engineConfiguration.getService(pid);
        if (ps == null)
            return;
        BizDao dao = ps.getBizDao();
        FieldDo[] data = dao.selectOne("SELECT entity,contexts,createUser FROM sys_job_info WHERE id=?", Arrays.asList(new FieldDo(FieldType.LONG, id)));
        if (data == null)
            return;
        LogicBean entity = ps.getEntityHandler().getEntity((String) data[0].getValue());
        if (entity == null)
            return;
        if (log.isDebugEnabled())
            log.debug(String.format("Execute Job %s [%s]", context.getJobDetail().getKey(), entity.getId()));
        EnvDo env = new EnvDo(pid, DeviceType.JOB, ps.getLocale().toString(), null, null);
        UserDo user = RuntimeUtils.createGustUser((String) data[2].getValue(), UserType.TYPE_OAUTH, env, ps);
        user.setIp("localhost");
        CommandContext cc = new CommandContext(engineConfiguration);
        cc.setupEnv(env);
        cc.setUser(user);
        Contexts.set(CommandContext.class, cc);
        try {
            List<FieldDo> fields = JSON.parseArray((String) data[1].getValue(), FieldDo.class);
            dao.update(null, "UPDATE sys_job_info SET status=?,code=?,message=? WHERE id=?", true, 1, null, null, id);
            Map<String, Object> systemVariables = new HashMap<String, Object>();
            RuntimeUtils.initWorkflow(systemVariables, null);
            RecordContext rc = new RecordContext(new Record(), systemVariables, new HashMap<>());
            fields.forEach(field -> {
                rc.setVariable(field);
            });
            rc.setVariable(new FieldDo("JOB_ID", FieldType.LONG, id));
            cc.beginTx();
            String code = RuntimeUtils.eval(cc, entity, rc);
            if (!code.equals("0000")) {
                cc.rollbackTx();
                dao.update(null, "UPDATE sys_job_info SET status=?,code=?,message=? WHERE id=?", true, 2, code, cc.getMessage(code, rc), id);
            } else {
                cc.commitTx();
                dao.update(null, "UPDATE sys_job_info SET status=?,code=?,message=? WHERE id=?", true, 3, "0000", null, id);
            }
        } catch (Exception ex) {
            if (log.isErrorEnabled())
                log.error("Execute Job :" + entity.getId(), ex);
            cc.rollbackTx();
            String msg;
            if (ex instanceof EasyPlatformWithLabelKeyException) {
                EasyPlatformWithLabelKeyException e = (EasyPlatformWithLabelKeyException) ex;
                msg = I18N.getLabel(e.getMessage(), e.getArgs());
            } else if (ex instanceof ScriptEvalException) {
                ScriptEvalException e = (ScriptEvalException) ex;
                msg = I18N.getLabel("script.engine.eval.error.2",
                        e.getSource(), e.getLine(), ex.getMessage());
            } else
                msg = ex.getMessage();
            dao.update(null, "UPDATE sys_job_info SET status=?,code=?,message=? WHERE id=?", true, 2, "e001", msg, id);
        } finally {
            SecurityUtils.getSubject().logout();
            Contexts.clear();
        }
    }
}
